package cn.lycode.generator.core;

import cn.lycode.common.core.domain.entity.SysMenu;
import cn.lycode.common.enums.TrueFalseEnum;
import cn.lycode.common.utils.DateUtils;
import cn.lycode.common.utils.SpringUtils;
import cn.lycode.common.utils.StringUtils;
import cn.lycode.generator.core.util.GeneratorUtils;
import cn.lycode.generator.domian.vo.GeneratorDetailVO;
import cn.lycode.generator.mapper.GeneratorTableMapper;

import java.io.File;
import java.nio.file.Paths;
import java.util.*;

public class CodeModelBuilder {
    private final Map<String, Object> model = new HashMap<>();
    // vue 文件夹路径分隔符
    public static final String SEPARATOR = "/";

    public CodeModelBuilder builderBaseInfo(GeneratorDetailVO detailVO) {
        String className = detailVO.getBaseInfo().getClassName();
        String packageName = detailVO.getGeneratorInfo().getPackageName();
        String router = getRouter(detailVO); // 路由名
        String tableName = detailVO.getBaseInfo().getTableName(); // 表名，例如sys_user
        String functionName = detailVO.getGeneratorInfo().getFunctionName(); // 方法名或业务名，例如：教师统计
        String businessName = detailVO.getGeneratorInfo().getBusinessName();
        List<GeneratorDetailVO.Column> columns = detailVO.getColumns();

        model.put("packageName", packageName);
        model.put("tableComment", detailVO.getBaseInfo().getTableComment());
        model.put("author", detailVO.getBaseInfo().getFunctionAuthor());
        model.put("datetime", DateUtils.getDefaultDate());
        model.put("tableName", tableName);
        model.put("className", className);
        model.put("camelClassName", detailVO.getBaseInfo().getCamelClassName());
        model.put("columns", columns);
        model.put("columnsExBase", GeneratorUtils.getColumnsExBase(columns));
        model.put("functionName", functionName);
        model.put("businessName", businessName);
        model.put("GeneratorInfo", detailVO.getGeneratorInfo());
        model.put("router", router);
        return this;
    }



    /**
     * 构建引包用的属性
     */
    public CodeModelBuilder builderImportPackage(GeneratorDetailVO detailVO) {
        List<GeneratorDetailVO.Column> columns = detailVO.getColumns();
        Set<String> importPackages = new TreeSet<>();
        boolean hasUniqueValidField = false;
        boolean hasDateFormat = false;
        boolean hasSort = false;
        for (GeneratorDetailVO.Column column : columns) {
            //Java类型需要引入的包
                String javaTypePackage = column.getJavaTypePackage();
            if (StringUtils.isNotNull(javaTypePackage)) {
                importPackages.add(javaTypePackage);
            }
            if (("LocalDateTime").equals(column.getJavaType())) {
                hasDateFormat = true;
            }
            if (("1").equals(column.getIsUniqueValid())) {
                hasUniqueValidField = true;
            }
            if (("sort").equals(column.getColumnName())) {
                hasSort = true;
            }
        }
        /*if (hasDateFormat) {
            importPackages.add("org.springframework.format.annotation.DateTimeFormat");
        }*/
        model.put("importPackages", importPackages);
        model.put("hasUniqueValidField", hasUniqueValidField);
        model.put("hasDateFormat", hasDateFormat);
        model.put("hasSort", hasSort);
        return this;
    }


    /**
     * 构建动态参数
     * 是否主键、是否select、是否excel
     */
    public CodeModelBuilder builderDynamicsParam(GeneratorDetailVO detailVO) {
        String idType = "";
        String pkName = "";
        String pkColumn = "id";
        boolean hasDict = false;
        boolean hasSelect = false;
        boolean hasExcel = false;


        //所有列
        List<GeneratorDetailVO.Column> columns = detailVO.getColumns();

        boolean hasGenExcel = ("1").equals(detailVO.getGeneratorInfo().getHasImport()) || ("1").equals(detailVO.getGeneratorInfo().getHasExport());

        for (GeneratorDetailVO.Column column : columns) {
            if (hasGenExcel && (("1").equals(column.getIsImport()) || ("1").equals(column.getIsExport()))) {
                hasExcel = true;
            }

            if (("1").equals(column.getIsPk())) {
                idType = column.getTsType();
                pkName = column.getJavaField();
                pkColumn = column.getColumnName();
            }
            if (StringUtils.isNotNull(column.getDictType())) {
                hasDict = true;
            }
            //HTML显示类型为 select 、radio
            if (("select").equals(column.getHtmlType()) || ("radio").equals(column.getHtmlType())) {
                hasSelect = true;
            }
        }
        model.put("pkColumn", pkColumn);
        model.put("pkName", pkName);
        //主键ts类型
        model.put("idType", idType);
        model.put("hasDict", hasDict);
        model.put("hasSelect", hasSelect);
        model.put("hasExcel", hasExcel);

        //主键列
        return this;
    }


    /**
     * 构建Java对象
     */
    public CodeModelBuilder builderJavaClass(GeneratorDetailVO detailVO) {
        String packageGroup = detailVO.getGeneratorInfo().getModuleName();
        String entityPkg = buildPackagePath(detailVO, packageGroup, "domain" + File.separator + "entity");
        String mapperPkg = buildPackagePath(detailVO, packageGroup, "mapper");
        String servicePkg = buildPackagePath(detailVO, packageGroup, "service");
        String serviceImplPkg = buildPackagePath(detailVO, packageGroup, "service" + File.separator + "impl");
        String controllerPkg = buildPackagePath(detailVO, packageGroup, "controller");
        String mapperXmlPkg = Paths.get("mapper", packageGroup).toString();
        String dtoPkg = buildPackagePath(detailVO, packageGroup, "domain" + File.separator + "dto" + File.separator + getDtoDir(detailVO));
        String voPkg = buildPackagePath(detailVO, packageGroup, "domain" + File.separator + "vo");

        model.put("entityPkg", entityPkg);
        model.put("mapperPkg", mapperPkg);
        model.put("mapperXmlPkg", mapperXmlPkg);
        model.put("servicePkg", servicePkg);
        model.put("serviceImplPkg", serviceImplPkg);
        model.put("controllerPkg", controllerPkg);
        model.put("dtoPkg", dtoPkg);
        model.put("voPkg", voPkg);

        model.put("entityClassName", detailVO.getBaseInfo().getClassName());
        model.put("mapperClassName", detailVO.getBaseInfo().getClassName() + "Mapper");
        model.put("serviceClassName", detailVO.getBaseInfo().getClassName() + "Service");
        model.put("serviceImplClassName", detailVO.getBaseInfo().getClassName() + "ServiceImpl");
        model.put("controllerClassName", detailVO.getBaseInfo().getClassName() + "Controller");
        model.put("dtoAddClassName", detailVO.getBaseInfo().getClassName() + "AddDTO");
        model.put("dtoUpdateClassName", detailVO.getBaseInfo().getClassName() + "UpdateDTO");
        model.put("dtoListClassName", detailVO.getBaseInfo().getClassName() + "ListDTO");
        model.put("dtoImportClassName", detailVO.getBaseInfo().getClassName() + "ImportDTO");
        model.put("voClassName", detailVO.getBaseInfo().getClassName() + "VO");

        boolean vueNeedSetSort = false;
        for (GeneratorDetailVO.Column column : detailVO.getColumns()) {

            if (("sort").equals(column.getJavaField()) && (("1").equals(column.getIsEdit()) || ("1").equals(column.getIsInsert()))) {
                vueNeedSetSort = true;
            }

        }
        model.put("vueNeedSetSort", vueNeedSetSort);
        return this;
    }

    /**
     * 构建Vue内容需要的model 变量
     */
    public CodeModelBuilder builderVue(GeneratorDetailVO detailVO) {
        String className = detailVO.getBaseInfo().getClassName();
        String interfacePkg = SEPARATOR + "api" + SEPARATOR + "interface" + SEPARATOR + detailVO.getGeneratorInfo().getModuleName();
        model.put("interfacePkg", interfacePkg);
        model.put("interfaceClassName", detailVO.getGeneratorInfo().getBusinessName());
        model.put("interfaceNamespace", "I" + detailVO.getBaseInfo().getClassName());

        String modulesPkg = SEPARATOR + "api" + SEPARATOR + "modules" + SEPARATOR + detailVO.getGeneratorInfo().getModuleName();
        model.put("modulesPkg", modulesPkg);
        model.put("modulesClassName", detailVO.getGeneratorInfo().getBusinessName());

        String indexPkg = SEPARATOR + "views" + SEPARATOR + detailVO.getGeneratorInfo().getModuleName() + SEPARATOR + detailVO.getGeneratorInfo().getBusinessName();
        model.put("indexPkg", indexPkg);
        model.put("indexClassName", "index");

        String formPkg = indexPkg + SEPARATOR + "components";
        model.put("formPkg", formPkg);
        model.put("formClassName", detailVO.getBaseInfo().getClassName() + "Form");

        model.put("funGetList", "get" + className + "ListApi");
        model.put("funAdd", "add" + className + "Api");
        model.put("funUpdate", "update" + className + "Api");
        model.put("funDetail", "get" + className + "DetailApi");
        model.put("funRemove", "remove" + className + "Api");
        model.put("funImport", "import" + className + "ExcelApi");
        model.put("funExport", "export" + className + "ExcelApi");

        // permission标识 TODO-完善  permission标识应有模块:业务:增删改查  构造
        String permissionHeader = getRouter(detailVO).replace("-", ":");
        String infoPermission = permissionHeader + ":info";
        String addPermission = permissionHeader + ":add";
        String updatePermission = permissionHeader + ":update";
        String removePermission = permissionHeader + ":remove";
        String importPermission = permissionHeader + ":import";
        String exportPermission = permissionHeader + ":export";
        String listPermission = permissionHeader + ":list";

        model.put("infoPermission", infoPermission);
        model.put("addPermission", addPermission);
        model.put("updatePermission", updatePermission);
        model.put("removePermission", removePermission);
        model.put("importPermission", importPermission);
        model.put("exportPermission", exportPermission);
        model.put("listPermission", listPermission);
        model.put("indexDefineOptionsName", className + "View"); // vue index DefineOptionsName

        return this;
    }

    /**
     * 构建菜单权限SQL需要的信息 主菜单、按钮菜单（增、删、改、查、导入、导出）
     */
    public CodeModelBuilder builderMenuSql(GeneratorDetailVO detailVO) {
        GeneratorTableMapper generatorTableMapper = SpringUtils.getBean(GeneratorTableMapper.class);
        //先查出父菜单
        Long parentMenuId = detailVO.getGeneratorInfo().getParentMenuId();
        SysMenu sysMenuParent = generatorTableMapper.selectSysMenuByPid(parentMenuId);
        int count = generatorTableMapper.selectMenuCount(parentMenuId); //子菜单个数，用于计算排序
        int menuDeep; //有父菜单，父级层级+1. 否则层级为1
        if (sysMenuParent != null) {
            menuDeep = sysMenuParent.getDeep() + 1;
        } else {
            menuDeep = 1;
        }

        //菜单路由名，为 类名 + "View" eg: SysPostView  //TODO-完善 类名去前缀生成
        String routerName = model.get("indexDefineOptionsName").toString();
        //菜单path   /模块名/类名首字母小写     eg:system/sysPost    //TODO-完善 类名去前缀生成
        String path = SEPARATOR + detailVO.getGeneratorInfo().getModuleName() + SEPARATOR + detailVO.getBaseInfo().getCamelClassName();
        //菜单组件    /模块名/类名首字母小写/index  eg:system/sysPost/index
        String component = path + SEPARATOR + "index";
        //表名横杠换成: + :list   eg:sys:post:list  TODO-完善  去掉表前缀之后， 模块名:业务名:增删改查
        String listPermission = model.get("listPermission").toString();

        //设置菜单模板变量
        SysMenu sysMenu = new SysMenu();
        if (StringUtils.isNotNull(parentMenuId)) {
            sysMenu.setPid(parentMenuId);
        }
        sysMenu.setPath(path);
        sysMenu.setName(routerName);
        sysMenu.setTitle(detailVO.getGeneratorInfo().getFunctionName());
        sysMenu.setIcon("");
        sysMenu.setComponent(component);
        sysMenu.setMenuSort((count * 100 + 100));
        sysMenu.setDeep(menuDeep);
        sysMenu.setMenuType("10020002"); // 菜单  //TODO-完善 用常量代替
        sysMenu.setPerms(listPermission);
        sysMenu.setHasChildren(TrueFalseEnum.F);
        model.put("menu", sysMenu);
        model.put("btnMenuType", "10020003"); //TODO-完善 用常量代替
        return this;
    }

    public Map<String, Object> getModel() {
        return this.model;
    }

    /**
     *
     * @param detailVO 获取配置的项目跟目录 controller目录上一级
     * @param packageGroup //packageGroup 就是moduleName
     * @param subPackage // controller、service、mapper、domain这些
     * @return packagePath
     */
    private static String buildPackagePath(GeneratorDetailVO detailVO, String packageGroup, String subPackage) {
        String basePackage = detailVO.getGeneratorInfo().getPackageName();
        return Paths.get(basePackage, packageGroup, subPackage).toString().replace(File.separator, ".");

    }

    /**
     * 路由名，
     * @param detailVO 表名去掉下划线  （TODO 后期研究下是否去掉表前缀）
     * @return 路由名
     */
    private static String getRouter(GeneratorDetailVO detailVO) {
        return detailVO.getBaseInfo().getTableName().replace("_", "-");
    }

    private static String getDtoDir(GeneratorDetailVO detailVO) {
        return detailVO.getBaseInfo().getTableName().replace("_", "").replace("-", "");
    }

}
